home *** CD-ROM | disk | FTP | other *** search
/ Graphics Plus / Graphics Plus.iso / msdos / utils / cad3d2ra.zoo / cad3dobj.c < prev    next >
C/C++ Source or Header  |  1994-03-14  |  9KB  |  317 lines

  1. /*
  2.  * cad3d2obj - the Atari CAD-3D file format
  3.  * $Id: cad3dobj.c,v 1.1 1994/03/14 15:22:52 herborth Exp $
  4.  *
  5.  * Chris Herborth
  6.  * March 7/94
  7.  *
  8.  * These are the functions you need to load a CAD-3D 2.x file and do
  9.  * something useful with it.  See cad3dobj.h for the structs used
  10.  * here.
  11.  *
  12.  * Compile with -DLITTLE_ENDIAN if you've got a little-endian CPU
  13.  * (ex, Intel, Cyrix, AMD).
  14.  *
  15.  * $Log: cad3dobj.c,v $
  16.  * Revision 1.1  1994/03/14  15:22:52  herborth
  17.  * Initial revision
  18.  *
  19.  */
  20.  
  21. #include <stdio.h>
  22. #include "cad3dobj.h"
  23.  
  24. /* Load the header into our CAD3D_HEADER struct */
  25. short get_cad3d_header( FILE *fp, CAD3D_HEADER *head )
  26. {
  27.     short retval;
  28. #ifdef LITTLE_ENDIAN
  29.     short loop;
  30. #endif
  31.  
  32.     if( fp == NULL || head == NULL )
  33.         return -1;
  34.  
  35.     retval = fread( head, sizeof( CAD3D_HEADER ), 1, fp );
  36.  
  37.     if( retval != 1 )
  38.         return -1;
  39.  
  40.     /* This is disgusting.  I hate Intel. */
  41. #ifdef LITTLE_ENDIAN
  42.     head->file_id     = swap_short( head->file_id );
  43.     head->num_objects = swap_short( head->num_objects );
  44.  
  45.     head->light_a_flag = swap_short( head->light_a_flag );
  46.     head->light_b_flag = swap_short( head->light_b_flag );
  47.     head->light_c_flag = swap_short( head->light_c_flag );
  48.  
  49.     head->light_a_bright = swap_short( head->light_a_bright );
  50.     head->light_b_bright = swap_short( head->light_b_bright );
  51.     head->light_c_bright = swap_short( head->light_c_bright );
  52.     head->ambient_bright = swap_short( head->ambient_bright );
  53.  
  54.     head->light_a_z = swap_short( head->light_a_z );
  55.     head->light_b_z = swap_short( head->light_b_z );
  56.     head->light_c_z = swap_short( head->light_c_z );
  57.     head->light_a_y = swap_short( head->light_a_y );
  58.     head->light_b_y = swap_short( head->light_b_y );
  59.     head->light_c_y = swap_short( head->light_c_y );
  60.     head->light_a_x = swap_short( head->light_a_x );
  61.     head->light_b_x = swap_short( head->light_b_x );
  62.     head->light_c_x = swap_short( head->light_c_x );
  63.  
  64.     for( loop = 0; loop < 16; loop++ )
  65.         head->obj_palette[loop] = swap_short( head->obj_palette[loop] );
  66.  
  67.     for( loop = 0; loop < 16; loop++ )
  68.         head->colour_group[loop] = swap_short( head->colour_group[loop] );
  69.  
  70.     head->palette_type     = swap_short( head->palette_type );
  71.     head->wireframe_colour = swap_short( head->wireframe_colour );
  72.     head->outline_colour   = swap_short( head->outline_colour );
  73. #endif
  74.  
  75.     if( head->file_id != CAD3D_MAGIC )
  76.         return -2;
  77.  
  78.     return 0;
  79. }
  80.  
  81. /* Dump a CAD-3D 2.x header in a human-readable format to a stream */
  82. short dump_cad3d_header( FILE *fp, const CAD3D_HEADER *head )
  83. {
  84.     short loop;
  85.  
  86.     if( fp == NULL || head == NULL )
  87.         return -1;
  88.  
  89.     if( head->file_id == CAD3D_MAGIC )
  90.         fprintf( fp, "CAD3D 2.x File\n" );
  91.     else
  92.         fprintf( fp, "WARNING: Unknown file type %x!\n", head->file_id );
  93.  
  94.     fprintf( fp, "%d objects\n", head->num_objects );
  95.  
  96.     if( head->light_a_flag == 1 )
  97.         fprintf( fp, "Light A (%f, %f, %f) is on, brightness = %d.\n",
  98.                  (float)(head->light_a_x)/100.0,
  99.                  (float)(head->light_a_y)/100.0,
  100.                  (float)(head->light_a_z)/100.0, head->light_a_bright );
  101.     else
  102.         fprintf( fp, "Light A is off.\n" );
  103.  
  104.     if( head->light_b_flag == 1 )
  105.         fprintf( fp, "Light B (%f, %f, %f) is on, brightness = %d.\n",
  106.                  (float)(head->light_b_x)/100.0,
  107.                  (float)(head->light_b_y)/100.0,
  108.                  (float)(head->light_b_z)/100.0, head->light_b_bright );
  109.     else
  110.         fprintf( fp, "Light B is off.\n" );
  111.  
  112.     if( head->light_c_flag == 1 )
  113.         fprintf( fp, "Light C (%f, %f, %f) is on, brightness = %d.\n",
  114.                  (float)(head->light_c_x)/100.0,
  115.                  (float)(head->light_c_y)/100.0,
  116.                  (float)(head->light_c_z)/100.0, head->light_c_bright );
  117.     else
  118.         fprintf( fp, "Light C is off.\n" );
  119.  
  120.     fprintf( fp, "Ambient light brightness = %d.\n", head->ambient_bright );
  121.  
  122.     fprintf( fp, "Colour palette and colour groups:\n" );
  123.     for( loop = 0; loop < 16; loop++ )
  124.         fprintf( fp, "%2d: 0x%04x [%2d]\n", loop, head->obj_palette[loop],
  125.                  head->colour_group[loop] );
  126.  
  127.     switch( head->palette_type )
  128.     {
  129.         case 0:
  130.             fprintf( fp, "7-shade palette\n" );
  131.             break;
  132.         case 1:
  133.             fprintf( fp, "14-shade palette\n" );
  134.             break;
  135.         case 2:
  136.             fprintf( fp, "Custom palette\n" );
  137.             break;
  138.         default:
  139.             fprintf( fp, "WARNING: Unknown palette type %d!", head->palette_type );
  140.             break;
  141.     }
  142.  
  143.     fprintf( fp, "Wireframe colour %d\n", head->wireframe_colour );
  144.     fprintf( fp, "Outline colour %d\n", head->outline_colour );
  145.  
  146. /*    char reserved[150];         For future expansion (ha!)               */
  147.  
  148.     return 0;
  149. }
  150.  
  151. /* Completely load a CAD-3D object from a file, including its vertices */
  152. /* and triangles...                                                    */
  153. short get_cad3d_object( FILE *fp, CAD3D_OBJECT *obj )
  154. {
  155.     short retval;
  156.     unsigned short loop;
  157.  
  158.     /* Get the object's name... */
  159.     retval = fread( obj->name, sizeof( char ), 9, fp );
  160.     if( retval != 9 )
  161.         return -1;
  162.     
  163.     /* Get the number of vertices... */
  164.     retval = fread( &(obj->num_vertices), sizeof( short ), 1, fp );
  165.     if( retval != 1 )
  166.         return -1;
  167. #ifdef LITTLE_ENDIAN
  168.     obj->num_vertices = swap_short( obj->num_vertices );
  169. #endif
  170.  
  171.     /* Allocate RAM for the vertices and load them... */
  172.     obj->vertices = (CAD3D_VERTEX *)malloc( obj->num_vertices
  173.                                             * sizeof( CAD3D_VERTEX ) );
  174.     if( obj->vertices == NULL )
  175.         return -2;
  176.  
  177.     for( loop = 0; loop < obj->num_vertices; loop++ )
  178.     {
  179.         retval = get_cad3d_vertex( fp, &(obj->vertices[loop]) );
  180.         if( retval != 0 )
  181.             return -3;
  182.     }
  183.  
  184.     /* Get the number of triangles... */
  185.     retval = fread( &(obj->num_triangles), sizeof( short ), 1, fp );
  186. #ifdef LITTLE_ENDIAN
  187.     obj->num_triangles = swap_short( obj->num_triangles );
  188. #endif
  189.  
  190.     /* Allocate memory for the triangles and load them... */
  191.     obj->triangles = (CAD3D_TRIANGLE *)malloc( obj->num_triangles
  192.                                                * sizeof( CAD3D_TRIANGLE ) );
  193.     if( obj->triangles == NULL )
  194.         return -4;
  195.  
  196.     for( loop = 0; loop < obj->num_triangles; loop++ )
  197.     {
  198.         retval = get_cad3d_triangle( fp, &(obj->triangles[loop]) );
  199.         if( retval != 0 )
  200.             return -5;
  201.     }
  202.  
  203.     return 0;
  204. }
  205.  
  206. /* Dump a CAD-3D 2.x in a human-readable format... */
  207. short dump_cad3d_object( FILE *fp, const CAD3D_OBJECT *obj )
  208. {
  209.     fprintf( fp, "Object %s:\n", obj->name );
  210.     fprintf( fp, "    %d vertices\n", obj->num_vertices );
  211.     fprintf( fp, "    %d triangles\n", obj->num_triangles );
  212.     fprintf( fp, "    Vertices and triangles mercifully not dumped.\n" );
  213.  
  214.     return 0;
  215. }
  216.  
  217. /* Read a vertex from a CAD-3D 2.x object... */
  218. short get_cad3d_vertex( FILE *fp, CAD3D_VERTEX *vert )
  219. {
  220.     short retval;
  221.  
  222.     if( fp == NULL || vert == NULL )
  223.         return -1;
  224.  
  225.     retval = fread( vert, sizeof( CAD3D_VERTEX ), 1, fp );
  226.     if( retval != 1 )
  227.         return -2;
  228.  
  229. #ifdef LITTLE_ENDIAN
  230.     vert->x = swap_short( vert->x );
  231.     vert->y = swap_short( vert->y );
  232.     vert->z = swap_short( vert->z );
  233. #endif
  234.  
  235.     return 0;
  236. }
  237.  
  238. /* Read a triangle within a CAD-3D 2.x object... */
  239. short get_cad3d_triangle( FILE *fp, CAD3D_TRIANGLE *tri )
  240. {
  241.     short retval;
  242.  
  243.     if( fp == NULL || tri == NULL )
  244.         return -1;
  245.  
  246.     retval = fread( tri, sizeof( CAD3D_TRIANGLE ), 1, fp );
  247.     if( retval != 1 )
  248.         return -2;
  249.  
  250. #ifdef LITTLE_ENDIAN
  251.     tri->index_a = swap_short( tri->index_a );
  252.     tri->index_b = swap_short( tri->index_b );
  253.     tri->index_c = swap_short( tri->index_c );
  254.  
  255.     tri->colour_edge = swap_short( tri->colour_edge );
  256. #endif
  257.  
  258.     return 0;
  259. }
  260.  
  261. /* Given a CAD-3D 2.x header and a particular triangle in that object, */
  262. /* decide which colour is the "base" colour for that object.  CAD-3D   */
  263. /* does some shading, which is bogus for rendering; finding the "base" */
  264. /* colour will allow the renderer to do the shading.  Note that this   */
  265. /* "base" colour isn't the same "base" colour referenced in the CAD-3D */
  266. /* documentation; it's actually the "brightest" of the colours in the  */
  267. /* triangle's colour group.  Note also that colours are compared very  */
  268. /* stupidly; a slightly red colour (0x0100) will be "brighter" than a  */
  269. /* very yellow colour (0x0077).  If your object has a screwy base      */
  270. /* group arry, it will probably come out all red.                      */
  271. short cad3d_triangle_colour( const CAD3D_HEADER *head,
  272.                              const CAD3D_TRIANGLE *tri )
  273. {
  274.     short tri_colour,
  275.           group,
  276.           loop,
  277.           brightest;
  278.  
  279.     /* the low byte of colour_edge is the colour */
  280.     tri_colour = tri->colour_edge & 0x00ff;
  281.     group = head->colour_group[tri_colour];
  282.  
  283.     /* Scan the colour palette for the colours in this group. */
  284.     brightest = 0x0000;
  285.     for( loop = 0; loop < 16; loop++ )
  286.         if( head->colour_group[loop] == group
  287.          && head->obj_palette[loop] > brightest )
  288.             brightest = head->obj_palette[loop];
  289.  
  290.     /* TODO: replace that > comparison with a real "is colour A brighter */
  291.     /*       than colour B?" test.                                       */
  292.  
  293.     return brightest;
  294. }
  295.  
  296. /* Convert a given Atari BIOS colour to a "standard" RGB triad ranging */
  297. /* from 0.0 to 1.0 in each element; note that this assumes the 512-    */
  298. /* colour range of the original Atari ST, and will probably produce    */
  299. /* a bogus RGB triad for STe/TT/Falcon colour ranges (the STe/TT have  */
  300. /* a range of 4096 colours, while the Falcon has 15-bit colour); don't */
  301. /* use it for that.                                                    */
  302. short atari2rgb( const short atari, RGB_TRIAD *rgb )
  303. {
  304.     rgb->red   = (float)( ( atari & 0x0f00 ) >> 8 )/7.0;
  305.     rgb->green = (float)( ( atari & 0x00f0 ) >> 4 )/7.0;
  306.     rgb->blue  = (float)( atari & 0x000f )/7.0;
  307.  
  308.     return 0;
  309. }
  310.  
  311. #ifdef LITTLE_ENDIAN
  312. short swap_short( const short s )
  313. {
  314.     return ( (s & 0x00ff) << 8 ) | ( (s & 0xff00) >> 8 );
  315. }
  316. #endif
  317.